<template>
  <div id="editor" class="editor" :style="editorStyle"
    @contextmenu="handleContextMenu" @mousedown="handleMouseDown">
    <shape v-for="(comp,index) in pageComponents" :key="comp.id"
      :default-style="comp.attr" :style="getShapeStyle(comp,index)"
      :active="comp.id === (curComponent || {}).id" :element="comp"
      :index="index">
      <component :is="comp.type" :id="'component' + comp.id"
        :child="comp.children ? comp.children:[]" class="component"
        :style="getComponentStyle(comp.attr)" :prop-value="comp.propValue"
        :element="comp" />
    </shape>
    <!-- 右击菜单 -->
    <canvas-contextmenu></canvas-contextmenu>
    <!-- 选中区域 -->
    <canvas-area v-show="isShowArea" :start="startArea" :width="widthArea"
      :height="heightArea" />
  </div>
</template>
<script>
import {
  onMounted,
  computed,
  defineAsyncComponent,
  defineComponent,
  ref,
} from "vue";
import { useDesignStore } from "../../../../../../store/design";
import {
  getStyle,
  getComponentRotatedStyle,
} from "../../../../../../utils/style";
const shape = defineAsyncComponent(() => import("./shape.vue"));
const CanvasContextmenu = defineAsyncComponent(() =>
  import("./canvas-contextmenu.vue")
);
const CanvasArea = defineAsyncComponent(() => import("./canvas-area.vue"));
export default defineComponent({
  name: "canvas-editor",
  components: {
    shape,
    CanvasContextmenu,
    CanvasArea,
  },
  setup() {
    const designStore = useDesignStore();
    const isShowArea = ref(true);
    const widthArea = ref(0);
    const heightArea = ref(0);
    const editorX = ref(0);
    const editorY = ref(0);
    const startArea = ref({
      x: 0,
      y: 0,
    });
    const pageConfig = computed(() => designStore.pageConfig);
    const editorStyle = computed(() => {
      return {
        width: `${pageConfig.value.width}px`,
        height: `${pageConfig.value.height}px`,
      };
    });
    const pageComponents = computed(() => designStore.pageComponents);
    const curComponent = computed(() => designStore.curComponent);
    const editor = computed(() => designStore.editor);
    const handleContextMenu = (e) => {
      e.stopPropagation();
      e.preventDefault();
      // 计算菜单相对于编辑器的位移
      let target = e.target;
      let top = e.offsetY;
      let left = e.offsetX;
      while (target instanceof SVGElement) {
        target = target.parentNode;
      }
      while (!target.className.includes("editor")) {
        left += target.offsetLeft;
        top += target.offsetTop;
        target = target.parentNode;
      }
      designStore.showContextMenu({ top, left });
    };
    const handleMouseDown = (e) => {
      if (!curComponent.value) {
        e.preventDefault();
      }
      hideArea();
      const rectInfo = editor.value.getBoundingClientRect();
      editorX.value = rectInfo.x;
      editorY.value = rectInfo.y;
      console.log(rectInfo.x);
      const startX = e.clientX;
      const startY = e.clientY;
      startArea.value.x = (startX - editorX.value) / pageConfig.value.scale;
      startArea.value.y = (startY - editorY.value) / pageConfig.value.scale;
      // 展示选中区域
      isShowArea.value = true;
      const move = (moveEvent) => {
        widthArea.value =
          Math.abs(moveEvent.clientX - startX) / pageConfig.value.scale;
        heightArea.value =
          Math.abs(moveEvent.clientY - startY) / pageConfig.value.scale;
        if (moveEvent.clientX < startX) {
          startArea.value.x =
            (moveEvent.clientX - editorX.value) / pageConfig.value.scale;
        }
        if (moveEvent.clientY < startY) {
          startArea.value.y =
            (moveEvent.clientY - editorY.value) / pageConfig.value.scale;
        }
      };
      const up = (e) => {
        document.removeEventListener("mousemove", move);
        document.removeEventListener("mouseup", up);
        if (e.clientX == startX && e.clientY == startY) {
          hideArea();
          return;
        }
        createGroup();
      };
      document.addEventListener("mousemove", move);
      document.addEventListener("mouseup", up);
    };
    const hideArea = () => {
      isShowArea.value = false;
      widthArea.value = 0;
      heightArea.value = 0;
      designStore.setAreaData({
        attr: {
          left: 0,
          top: 0,
          width: 0,
          height: 0,
          rotate: 0,
        },
        components: [],
      });
    };
    const createGroup = () => {
      // 获取选中区域的组件数据
      const areaData = getSelectArea();
      if (areaData.length <= 1) {
        hideArea();
        return;
      }
      // 根据选中区域和区域中每个组件的位移信息来创建 Group 组件
      // 要遍历选择区域的每个组件，获取它们的 left top right bottom 信息来进行比较
      let top = Infinity,
        left = Infinity;
      let right = -Infinity,
        bottom = -Infinity;
      areaData.forEach((component) => {
        let attr = {
          left: 0,
          top: 0,
          right: 0,
          bottom: 0,
        };
        if (component.type == "van-group") {
          component.children.forEach((item) => {
            const rectInfo = $(`#component${item.id}`).getBoundingClientRect();
            attr.left = rectInfo.left * pageConfig.value.scale - editorX.value;
            attr.top = rectInfo.top * pageConfig.value.scale - editorY.value;
            attr.right =
              rectInfo.right * pageConfig.value.scale - editorX.value;
            attr.bottom =
              rectInfo.bottom * pageConfig.value.scale - editorY.value;
            if (attr.left < left) left = attr.left;
            if (attr.top < top) top = attr.top;
            if (attr.right > right) right = attr.right;
            if (attr.bottom > bottom) bottom = attr.bottom;
          });
        } else {
          if (!component.hided) {
            attr = getComponentRotatedStyle(component.attr);
          }
        }
        console.log(attr,"attr");
        if (attr.left < left) left = attr.left;
        if (attr.top < top) top = attr.top;
        if (attr.right > right) right = attr.right;
        if (attr.bottom > bottom) bottom = attr.bottom;
      });
      startArea.value.x = left;
      startArea.value.y = top;
      widthArea.value = right - left;
      heightArea.value = bottom - top;
      // 设置选中区域位移大小信息和区域内的组件数据
      designStore.setAreaData({
        attr: {
          left,
          top,
          width: widthArea.value,
          height: heightArea.value,
        },
        components: areaData,
      });
    };
    const getSelectArea = () => {
      const result = [];
      // 区域起点坐标
      const { x, y } = startArea.value;
      // 计算所有的组件数据，判断是否在选中区域内
      pageComponents.value.forEach((component) => {
        if (component.hided) return;
        const { left, top, width, height } = getComponentRotatedStyle(
          component.attr
        );
        console.log(left, top, width, height,"left, top, width, height");
        if (
          x <= left * pageConfig.value.scale &&
          y <= top * pageConfig.value.scale &&
          (left + width) * pageConfig.value.scale <= x + widthArea.value &&
          (top + height) * pageConfig.value.scale <= y + heightArea.value
        ) {
          result.push(component);
        }
      });
      // 返回在选中区域内的所有组件
      return result;
    };
    const getShapeStyle = (comp, index) => {
      const style = comp.attr;
      const result = {
        zIndex: index,
        display: comp.hided ? "none" : "block",
      };
      ["width", "height", "top", "left", "rotate"].forEach((attr) => {
        if (attr != "rotate") {
          result[attr] = style[attr] + "px";
        } else {
          result.transform = "rotate(" + style[attr] + "deg)";
        }
      });
      return result;
    };
    const getComponentStyle = (style) => {
      let scaleX = `${style.filpH ? -1 : 1}`;
      let scaleY = `${style.filpV ? -1 : 1}`;
      return {
        transform: `scaleX(${scaleX}) scaleY(${scaleY}) rotateZ(360deg)`,
        height:'100%',
        with:'100%'
      };
    };
    onMounted(() => {
      designStore.getEditor();
    });
    return {
      editorX,
      editorY,
      isShowArea,
      curComponent,
      pageConfig,
      editorStyle,
      heightArea,
      widthArea,
      startArea,
      pageComponents,
      getShapeStyle,
      handleContextMenu,
      handleMouseDown,
      getComponentStyle,
      hideArea,
      createGroup,
      getSelectArea,
    };
  },
});
</script>